﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Threading;

namespace CYTS.Aoyou.Framework.Utility
{
    public class SqlMapCache
    {
        public volatile static Dictionary<string,SqlMapConfig> SqlMapDic = new Dictionary<string,SqlMapConfig>();
        private volatile static Dictionary<string, FileInfo> FileInfoDic = null;
        private static int updateTimeSpan = 2*60*1000;
        private static object LockObj = new object();

        public static string SqlMapPath 
        {
            get 
            {
                try
                {
                    string configPath = System.Configuration.ConfigurationManager.AppSettings["SqlMapPath"].ToString();
                    configPath = System.IO.Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\" + configPath);
                    return configPath;
                }
                catch (Exception ex)
                {
                    string msg = "SqlMapPath读取失败";
                    //EmailHelper.SendMail("", _ErrorEmailTo, _ErrorEmailSubject, false, msg + "\n" + ex, "", "");
                    throw new Exception(msg, ex);
                }
                
            }
        }

        static SqlMapCache() 
        {
            if(SqlMapDic.Count==0)
            {
                GetFileInfo(new DirectoryInfo(SqlMapPath));
            }
            ThreadPool.QueueUserWorkItem(UpdateSqlMapCache,null);
        }

        /// <summary>
        /// 更新sqlMapCache
        /// </summary>
        public static void UpdateSqlMapCache(object param) 
        {
            while(true)
            {
                Thread.Sleep(updateTimeSpan);
                DirectoryInfo di = new DirectoryInfo(SqlMapPath);
                
                lock(LockObj)
                {
                    if (FileInfoDic == null)
                    {
                        FileInfoDic = new Dictionary<string, FileInfo>();
                    }
                    else 
                    {
                        FileInfoDic.Clear();
                    }

                    var files = di.GetFiles("*.sqlmap", SearchOption.AllDirectories);
                    foreach (var item in files)
                    {
                        FileInfoDic.Add(item.Name.Replace(".sqlmap", ""), item);
                    }
                }

                while(true)
                {
                    GetFileInfo(di);
                    Thread.Sleep(updateTimeSpan);
                }
            }
        }

        private static void GetFileInfo(DirectoryInfo di) 
        {
            try 
            {
                Monitor.Enter(LockObj);
                if (FileInfoDic == null)
                {
                    FileInfoDic = new Dictionary<string, FileInfo>();
                }
                else
                {
                    FileInfoDic.Clear();
                }
                List<FileInfo> fileList = new List<FileInfo>();
                fileList = di.GetFiles("*.sqlmap", SearchOption.AllDirectories).ToList();
                foreach (var file in fileList)
                {
                    if (!SqlMapDic.ContainsKey(file.Name.Replace(".sqlmap", "")) || !FileInfoDic.ContainsKey(file.Name.Replace(".sqlmap", "")) || (FileInfoDic.ContainsKey(file.Name.Replace(".sqlmap", "")) && file.LastWriteTime != FileInfoDic[file.Name.Replace(".sqlmap", "")].LastWriteTime))
                    {
                        OneUpdate(file.Name.Replace(".sqlmap", ""));
                    }
                }
            }
            catch(Exception ex)
            {
                string msg = "GetFileInfo方法错误";
                throw new Exception(msg, ex);
            }
            finally
            {
                Monitor.Exit(LockObj);
            }
        }


        /// <summary>
        /// 加载配置（反序列化本地文件）
        /// </summary>
        /// <returns></returns>
        public static void OneUpdate(string sqlMapName)
        {
            try
            {
                Monitor.Enter(LockObj);
                string filePath = SqlMapCache.SqlMapPath + sqlMapName + ".sqlmap";
                DirectoryInfo di = new DirectoryInfo(SqlMapPath);
                SqlMapConfig conf = SerializationHelper.Load(typeof(SqlMapConfig), filePath) as SqlMapConfig;

                if (SqlMapDic.ContainsKey(sqlMapName))
                {
                    SqlMapDic.Remove(sqlMapName);
                }
                SqlMapDic.Add(sqlMapName, conf);

                if (FileInfoDic.ContainsKey(sqlMapName))
                {
                    FileInfoDic.Remove(sqlMapName);
                }
                FileInfoDic.Add(sqlMapName, di.GetFiles(sqlMapName + ".sqlmap", SearchOption.AllDirectories).FirstOrDefault());
            }
            catch (Exception ex)
            {
                string msg = typeof(SqlMapConfig).ToString() + "文件序列化错误";
                throw new Exception(msg, ex);
            }
            finally 
            {
                Monitor.Exit(LockObj);
            }
        }


        public static SqlMapConfig GetSqlMapConfig(string key) 
        {
            if (SqlMapDic.ContainsKey(key))
            {
                return SqlMapDic[key];
            }
            else 
            {
                if(SqlMapDic.ContainsKey(key))
                {
                    return SqlMapDic[key];   
                }
                else
                {
                    return null;
                }
            }
        }
    }
}
